#include "local_options.h"
#include <stdio.h>
#include <stdlib.h>

namespace examples {

const local_options::device_type local_options::defaults::device =
  local_options::device_types::serial;

const char* local_options::defaults::serial_path = "/dev/ttyUSB0";

const char* local_options::defaults::socket_address = "localhost";
const uint16_t local_options::defaults::socket_port = 9675;

const int local_options::defaults::time = 0;
const bool local_options::defaults::single = false;

const bool local_options::defaults::remote = false;

const char* local_options::short_options = "hs:a:p:t:or";

const struct option local_options::long_options[] = 
{
  // Show help
  {"help", optional_argument, 0, 'h'},
  // Serial 
  {"serial", optional_argument, 0, 's'},
  // Address
  {"address", optional_argument, 0, 'a'},
  // Port
  {"port", optional_argument, 0, 'p'},
  // Time
  {"time", optional_argument, 0, 't'},
  // One by one 
  {"one", optional_argument, 0, 'o'},
  // Remote
  {"remote", optional_argument, 0, 'r'},
  // Keyboard contrl
 {"keyboard", optional_argument, 0, 'k'},
  {0, 0, 0, 0}
};

local_options::local_options(int argc, char* const argv[])
  : argc(argc),
    argv(argv),
    device(defaults::device),
    serial_path(defaults::serial_path),
    socket_address(defaults::socket_address),
    socket_port(defaults::socket_port),
    time(defaults::time),
    single(defaults::single),
    remote(defaults::remote),
    keyboard(false)
{

}

bool local_options::parse(int argc, char* const argv[])
{
  local_options::argc = argc;
  local_options::argv = argv;
  
  return parse();
}

bool local_options::parse()
{
  int index = 0;
  int arg = 0;

  while ((arg = getopt_long(argc, argv, short_options, long_options,
    &index)) != -1)
  {
    switch(arg)
    {
    case 'h':
      usage();
      return false;
    case 's':
      device = device_types::serial;
      serial_path = optarg;
      break;
    case 'a':
      device = device_types::socket;
      socket_address = optarg;
      break;
    case 'p':
      device = device_types::socket;
      socket_port = atoi(optarg);
      break;
    case 't':
      time = atoi(optarg);
      break;
    case 'o':
      single = true;
      break;
    case 'r':
      remote = true;
      break;
    case 'k':
	keyboard = true;
	break;
    default:
      usage();
      printf("option %s\n", optarg);
      throw runtime_error("Could not parse command line arguments");
      return false;
    };
  }
  
  return true;
}

void local_options::usage()
{
  printf("Usage: %s [OPTIONS]\n", argv[0]);
  puts("  -h, --help              show usage");
  puts("  -s, --serial=PATH       thinklink serial path");
  puts("  -a, --address=ADDRESS   thinklink socket address");
  puts("  -p, --port=PORT         thinklink socket port");
  puts("  -t, --time=NUMBER       time between each iteration");
  puts("  -o, --one               iteration is a single actuator");
  puts("  -r, --remote            use remote robot");
  puts("  -k, --keyboard          use keyboard control of robot, otherwise explore");
}

} // namespace examples
